package router

import (
	"context"
	"fmt"
	v1 "ginblog/api/v1"
	"ginblog/config"
	//_ "ginblog/docs"
	"ginblog/middleware"
	"ginblog/model"
	errMsg "ginblog/model/err"
	"ginblog/model/request"
	"ginblog/model/response"
	"ginblog/vaildate"
	"github.com/gin-gonic/gin"
	gs "github.com/swaggo/gin-swagger"
	"github.com/swaggo/gin-swagger/swaggerFiles"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

// @title 这里写标题
// @version 1.0
// @description 这里写描述信息
// @termsOfService http://swagger.io/terms/

// @contact.name 这里写联系人信息
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io

// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html

// @host 这里写接口服务的host
// @BasePath 这里写base path
func InitRouter() {
	gin.SetMode("debug")
	r := gin.Default()
	r.GET("/swagger/*any", gs.WrapHandler(swaggerFiles.Handler))
	api := r.Group("api/v1")
	api.Use(middleware.Cors())
	{
		// 用户模块路由接口
		user := api.Group("user")
		{
			user.POST("", v1.AddUser)
			user.GET("", v1.GetUsers)
			user.PUT(":id", v1.Edit)
			user.DELETE("", v1.DeleteUser)
		}
		// 分类模块路由接口
		category := api.Group("category")
		{
			category.POST("", v1.AddCate)
			category.GET(":id", v1.GetCate)
			category.GET("", v1.GetCateList)
			category.DELETE(":id", v1.DeleteCate)
			category.PUT(":id", v1.EditCate)
		}
		// 文章模块路由接口
		article := api.Group("article")
		{
			article.POST("", v1.AddArticle)
			article.GET(":id", v1.GetArticle)
			//article.GET("", v1.GetArticleList)
			article.DELETE("", v1.DeleteArticle)
			article.PUT("", v1.EditArticle)
		}
		api.POST("/login", v1.Login)
		api.POST("/upload", v1.Upload)
	}
	r.POST("ok", func(c *gin.Context) {
		response.Ok(c, nil, "aaa")
	})
	r.POST("fail", func(c *gin.Context) {
		response.Fail(c, errMsg.DB_ERROR, nil)
	})
	r.POST("/test", func(c *gin.Context) {
		var p request.Login
		_ = c.ShouldBindJSON(&p)
		msg, code := vaildate.Validator(p)
		if code != errMsg.SUCCESS {
			response.Fail(c, errMsg.PARAM_ERROR, msg)
			return
		}
		response.Ok(c, p)
	})
	r.GET("token", func(c *gin.Context) {
		token, code := middleware.SetToken("1")
		if code != errMsg.SUCCESS {
			response.Fail(c, code, nil)
			return
		}
		response.Ok(c, token)
	})
	//r.Run(config.HttpPort)

	srv := NewServer(Addr(config.HttpPort), Handle(r))
	//srv := &http.Server{
	//    Addr:    config.HttpPort,
	//    Handler: r,
	//}
	go func() {
		// 开启一个goroutine启动服务
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("listen: %s\n", err)
		}
	}()

	// 等待中断信号来优雅地关闭服务器，为关闭服务器操作设置一个5秒的超时
	quit := make(chan os.Signal, 1) // 创建一个接收信号的通道
	// kill 默认会发送 syscall.SIGTERM 信号
	// kill -2 发送 syscall.SIGINT 信号，我们常用的Ctrl+C就是触发系统SIGINT信号
	// kill -9 发送 syscall.SIGKILL 信号，但是不能被捕获，所以不需要添加它
	// signal.Notify把收到的 syscall.SIGINT或syscall.SIGTERM 信号转发给quit
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) // 此处不会阻塞
	a := <-quit                                          // 阻塞在此，当接收到上述两种信号时才会往下执行
	fmt.Println("----------------中断信号：", a)
	log.Println("Shutdown Server ...")
	// 创建一个5秒超时的context
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	// 5秒内优雅关闭服务（将未处理完的请求处理完再关闭服务），超过5秒就超时退出
	if err := srv.Shutdown(ctx); err != nil {
		model.CloseDB()
		log.Fatal("Server Shutdown: ", err)
	}

	log.Println("Server exiting")
}
func NewServer(options ...Option) *http.Server {
	srv := &http.Server{}
	for _, option := range options {
		option(srv)
	}
	return srv
}

type Option func(server *http.Server)

func Addr(addr string) Option {
	return func(s *http.Server) {
		s.Addr = addr
	}
}

func Handle(h http.Handler) Option {
	return func(s *http.Server) {
		s.Handler = h
	}
}
